//
//  NLImagePickerHelper.m
//  nl_photo_picker
//
//  Created by 赵优路 on 2019/7/17.
//

#import "NLImagePickerHelper.h"
#import <AVFoundation/AVFoundation.h>
#import <MobileCoreServices/MobileCoreServices.h>
#import "NLPhotoAssetUtil.h"

static const int SOURCE_CAMERA = 0;
static const int SOURCE_GALLERY = 1;

@interface NLImagePickerHelper () <UINavigationControllerDelegate, UIImagePickerControllerDelegate,UIAlertViewDelegate>
@property(copy, nonatomic) FlutterResult result;
@end

@implementation NLImagePickerHelper
{
    NSDictionary *_arguments;
    UIImagePickerController *_imagePickerController;
    UIViewController *_viewController;
}

- (instancetype)init {
    self = [super init];
    if (self) {
        UIViewController *viewController =
        [UIApplication sharedApplication].delegate.window.rootViewController;
        _viewController = viewController;
        _imagePickerController = [[UIImagePickerController alloc] init];
    }
    return self;
}

- (instancetype)initWithViewController:(UIViewController *)viewController {
    self = [super init];
    if (self) {
        _viewController = viewController;
        _imagePickerController = [[UIImagePickerController alloc] init];
    }
    return self;
}

- (void)imagePickerhandleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result {
    if (self.result) {
        self.result([FlutterError errorWithCode:@"multiple_request"
                                    message:@"Cancelled by a second request"
                                    details:nil]);
        self.result = nil;
    }
    
    if ([@"pickImage" isEqualToString:call.method]) {
        _imagePickerController.modalPresentationStyle = UIModalPresentationCurrentContext;
        _imagePickerController.delegate = self;
        _imagePickerController.mediaTypes = @[ (NSString *)kUTTypeImage ];
        
        self.result = result;
        _arguments = call.arguments;
        
        int imageSource = [[_arguments objectForKey:@"source"] intValue];
        
        switch (imageSource) {
            case SOURCE_CAMERA:
                [self showCamera];
                break;
            case SOURCE_GALLERY:
                [self checkPhotoAuthorization];
                break;
            default:
                result([FlutterError errorWithCode:@"invalid_source"
                                           message:@"Invalid image source."
                                           details:nil]);
                break;
        }
    } else if ([@"pickVideo" isEqualToString:call.method]) {
        _imagePickerController.modalPresentationStyle = UIModalPresentationCurrentContext;
        _imagePickerController.delegate = self;
        _imagePickerController.mediaTypes = @[
                                              (NSString *)kUTTypeMovie, (NSString *)kUTTypeAVIMovie, (NSString *)kUTTypeVideo,
                                              (NSString *)kUTTypeMPEG4
                                              ];
        _imagePickerController.videoQuality = UIImagePickerControllerQualityTypeHigh;
        
        self.result = result;
        _arguments = call.arguments;
        
        int imageSource = [[_arguments objectForKey:@"source"] intValue];
        
        switch (imageSource) {
            case SOURCE_CAMERA:
                [self showCamera];
                break;
            case SOURCE_GALLERY:
                [self checkPhotoAuthorization];
                break;
            default:
                result([FlutterError errorWithCode:@"invalid_source"
                                           message:@"Invalid video source."
                                           details:nil]);
                break;
        }
    } else if ([@"saveImage" isEqualToString:call.method]) {
        self.result = result;
        _arguments = call.arguments;
        
        FlutterStandardTypedData* fileData = [_arguments objectForKey:@"fileData"] ;
        UIImage *image=[UIImage imageWithData:fileData.data];
        PHAuthorizationStatus status = [PHPhotoLibrary authorizationStatus];
        if (status == PHAuthorizationStatusRestricted || status == PHAuthorizationStatusDenied) {
          [self errorNoPhotoAccess:status];
        } else if (status == PHAuthorizationStatusAuthorized) { // if user chosen"Allow"
            [self saveImage:image];
        } else if (status == PHAuthorizationStatusNotDetermined) { // if user not chosen before
            // Requests authorization with dialog
            [PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) {
                if (status == PHAuthorizationStatusAuthorized) { //  if user  chosen "Allow"
                    //Save Image to Directory
                    [self saveImage:image];
                }else{
                    self.result(nil);
                    self.result = nil;
                    self->_arguments = nil;
                }
            }];
        }
    }
}
-(void)saveImage:(UIImage *)image  {
    
    __block NSString *localIdentifier = nil;
    [[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
        PHAssetChangeRequest *request = [PHAssetChangeRequest creationRequestForAssetFromImage:image];
        localIdentifier = request.placeholderForCreatedAsset.localIdentifier;
        request.creationDate = [NSDate date];
    } completionHandler:^(BOOL success, NSError * _Nullable error) {
        if (error) {
            self.result(nil);
        } else {
            NSLog(@"保存成功localIdentifier====%@",localIdentifier);
            self.result(localIdentifier);
        }
        self.result = nil;
        self->_arguments = nil;
        
    }];
}


- (void)showCamera {
    
    AVAuthorizationStatus authStatus = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
    if ((authStatus == AVAuthorizationStatusRestricted || authStatus ==AVAuthorizationStatusDenied)) {
        
        NSDictionary *infoDict = [self nl_getInfoDictionary];
        // 无权限 做一个友好的提示
        NSString *appName = [infoDict valueForKey:@"CFBundleDisplayName"];
        if (!appName) appName = [infoDict valueForKey:@"CFBundleName"];
        NSString *message = [NSString stringWithFormat:@"请在iPhone的\"设置-隐私-相机\"中允许%@访问相机",appName];
        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"无法使用相机" message:message delegate:self cancelButtonTitle:@"取消" otherButtonTitles:@"设置", nil];
        [alert show];
        self.result(nil);
        self.result = nil;
        _arguments = nil;
    } else if (authStatus == AVAuthorizationStatusNotDetermined) {
        // fix issue 466, 防止用户首次拍照拒绝授权时相机页黑屏
        [AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo completionHandler:^(BOOL granted) {
            if (granted) {
                dispatch_async(dispatch_get_main_queue(), ^{
                    [self pushImagePickerController];
                });
            }
        }];
    } else {
        [self pushImagePickerController];
    }
    // Camera is not available on simulators

    
}
- (NSDictionary *)nl_getInfoDictionary {
    NSDictionary *infoDict = [NSBundle mainBundle].localizedInfoDictionary;
    if (!infoDict || !infoDict.count) {
        infoDict = [NSBundle mainBundle].infoDictionary;
    }
    if (!infoDict || !infoDict.count) {
        NSString *path = [[NSBundle mainBundle] pathForResource:@"Info" ofType:@"plist"];
        infoDict = [NSDictionary dictionaryWithContentsOfFile:path];
    }
    return infoDict ? infoDict : @{};
}
-(void)pushImagePickerController{
    
    if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {
            _imagePickerController.sourceType = UIImagePickerControllerSourceTypeCamera;
            [_viewController presentViewController:_imagePickerController animated:YES completion:nil];
    
    } else {
        
            [[[UIAlertView alloc] initWithTitle:@"Error"
                                        message:@"Camera not available."
                                       delegate:nil
                              cancelButtonTitle:@"OK"
                              otherButtonTitles:nil] show];
        self.result(nil);
        self.result = nil;
        _arguments = nil;
    }
}

- (void)showPhotoLibrary {
    // No need to check if SourceType is available. It always is.
    _imagePickerController.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
    [_viewController presentViewController:_imagePickerController animated:YES completion:nil];
}
- (void)checkPhotoAuthorization {
    PHAuthorizationStatus status = [PHPhotoLibrary authorizationStatus];
    switch (status) {
        case PHAuthorizationStatusNotDetermined: {
            [PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) {
                if (status == PHAuthorizationStatusAuthorized) {
                    dispatch_async(dispatch_get_main_queue(), ^{
                        [self showPhotoLibrary];
                    });
                } else {
                    self.result(nil);
                    self.result = nil;
                    self->_arguments = nil;
                }
            }];
            break;
        }
        case PHAuthorizationStatusAuthorized:
            [self showPhotoLibrary];
            break;
        case PHAuthorizationStatusDenied:
        case PHAuthorizationStatusRestricted:
        default:
            [self errorNoPhotoAccess:status];
            break;
    }
}
- (void)errorNoPhotoAccess:(PHAuthorizationStatus)status {
    switch (status) {
        case PHAuthorizationStatusRestricted:
            self.result([FlutterError errorWithCode:@"photo_access_restricted"
                                            message:@"The user is not allowed to use the photo."
                                            details:nil]);
            break;
        case PHAuthorizationStatusDenied:
        default:
            self.result([FlutterError errorWithCode:@"photo_access_denied"
                                            message:@"The user did not allow photo access."
                                            details:nil]);
            break;
    }
    dispatch_async(dispatch_get_main_queue(), ^{
        NSDictionary *infoDict = [self nl_getInfoDictionary];
        // 无权限 做一个友好的提示
        NSString *appName = [infoDict valueForKey:@"CFBundleDisplayName"];
        if (!appName) appName = [infoDict valueForKey:@"CFBundleName"];
        NSString *message = [NSString stringWithFormat:@"请在iPhone的\"设置-隐私-相机\"中允许%@访问相册",appName];
        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"无法储存照片" message:message delegate:self cancelButtonTitle:@"取消" otherButtonTitles:@"设置", nil];
        [alert show];
    });
    
}


- (void)imagePickerController:(UIImagePickerController *)picker
didFinishPickingMediaWithInfo:(NSDictionary<NSString *, id> *)info {
    
    if (!self.result) {
        return;
    }
    [PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) {
        if (status == PHAuthorizationStatusAuthorized) {
            dispatch_async(dispatch_get_main_queue(), ^{
                [self->_imagePickerController dismissViewControllerAnimated:YES completion:nil];
            });
            
            [self saveActionWithInfo:info];
           
        } else {
            dispatch_async(dispatch_get_main_queue(), ^{
                NSDictionary *infoDict = [self nl_getInfoDictionary];
                // 无权限 做一个友好的提示
                NSString *appName = [infoDict valueForKey:@"CFBundleDisplayName"];
                if (!appName) appName = [infoDict valueForKey:@"CFBundleName"];
                NSString *message = [NSString stringWithFormat:@"请在iPhone的\"设置-隐私-相机\"中允许%@访问相册",appName];
                UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"无法访问相册" message:message delegate:self cancelButtonTitle:@"取消" otherButtonTitles:@"设置", nil];
                [alert show];
            });
        }
    }];
}
- (void)saveActionWithInfo:(NSDictionary<NSString *, id> *)info{
    
    NSURL *videoURL = [info objectForKey:UIImagePickerControllerMediaURL];
   
    
    if (videoURL != nil) {
        NSData *data = [NSData dataWithContentsOfURL:videoURL];
        NSString *guid = [[NSProcessInfo processInfo] globallyUniqueString];
        NSString *tmpFile = [NSString stringWithFormat:@"image_picker_%@.MOV", guid];
        NSString *tmpDirectory = NSTemporaryDirectory();
        NSString *tmpPath = [tmpDirectory stringByAppendingPathComponent:tmpFile];
        
        
        if ([[NSFileManager defaultManager] createFileAtPath:tmpPath contents:data attributes:nil]) {
            self.result(tmpPath);
        } else {
            self.result([FlutterError errorWithCode:@"create_error"
                                        message:@"Temporary file could not be created"
                                        details:nil]);
        }
    } else {
        
        PHAsset *originalAsset = [NLPhotoAssetUtil getAssetFromImagePickerInfo:info];
        
        if (originalAsset) {
//            __weak typeof(self) weakSelf = self;
            NSLog(@"图库取得的localIdentifier=====%@",originalAsset.localIdentifier);
            self.result(originalAsset.localIdentifier);
        }else{
            UIImage *image = [info objectForKey:UIImagePickerControllerEditedImage];
            if (image == nil) {
                image = [info objectForKey:UIImagePickerControllerOriginalImage];
            }
            image = [self normalizedImage:image];
            [self saveImage:image];
        }
        
    }
}
- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker {
    [_imagePickerController dismissViewControllerAnimated:YES completion:nil];
    self.result(nil);
    
    self.result = nil;
    _arguments = nil;
}

// The way we save images to the tmp dir currently throws away all EXIF data
// (including the orientation of the image). That means, pics taken in portrait
// will not be orientated correctly as is. To avoid that, we rotate the actual
// image data.
// TODO(goderbauer): investigate how to preserve EXIF data.
- (UIImage *)normalizedImage:(UIImage *)image {
    if (image.imageOrientation == UIImageOrientationUp) return image;
    
    UIGraphicsBeginImageContextWithOptions(image.size, NO, image.scale);
    [image drawInRect:(CGRect){0, 0, image.size}];
    UIImage *normalizedImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return normalizedImage;
}

- (UIImage *)scaledImage:(UIImage *)image
                maxWidth:(NSNumber *)maxWidth
               maxHeight:(NSNumber *)maxHeight {
    double originalWidth = image.size.width;
    double originalHeight = image.size.height;
    
    bool hasMaxWidth = maxWidth != (id)[NSNull null];
    bool hasMaxHeight = maxHeight != (id)[NSNull null];
    
    double width = hasMaxWidth ? MIN([maxWidth doubleValue], originalWidth) : originalWidth;
    double height = hasMaxHeight ? MIN([maxHeight doubleValue], originalHeight) : originalHeight;
    
    bool shouldDownscaleWidth = hasMaxWidth && [maxWidth doubleValue] < originalWidth;
    bool shouldDownscaleHeight = hasMaxHeight && [maxHeight doubleValue] < originalHeight;
    bool shouldDownscale = shouldDownscaleWidth || shouldDownscaleHeight;
    
    if (shouldDownscale) {
        double downscaledWidth = floor((height / originalHeight) * originalWidth);
        double downscaledHeight = floor((width / originalWidth) * originalHeight);
        
        if (width < height) {
            if (!hasMaxWidth) {
                width = downscaledWidth;
            } else {
                height = downscaledHeight;
            }
        } else if (height < width) {
            if (!hasMaxHeight) {
                height = downscaledHeight;
            } else {
                width = downscaledWidth;
            }
        } else {
            if (originalWidth < originalHeight) {
                width = downscaledWidth;
            } else if (originalHeight < originalWidth) {
                height = downscaledHeight;
            }
        }
    }
    
    UIGraphicsBeginImageContextWithOptions(CGSizeMake(width, height), YES, 1.0);
    [image drawInRect:CGRectMake(0, 0, width, height)];
    
    UIImage *scaledImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    
    return scaledImage;
}


#pragma mark - UIAlertViewDelegate

- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
    if (buttonIndex == 1) { // 去设置界面，开启相机访问权限
        [[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString]];
    }else{
        [_imagePickerController dismissViewControllerAnimated:YES completion:nil];
    }
    
}



@end
